home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Disc to the Future 2
/
Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin
/
MAC
/
THINKC
/
4_0
/
REXP_SRC
/
REPLACE.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-09-18
|
7KB
|
306 lines
#define ABOUT "usage: rep([flags],regular expression,replacement string,input text)\rrep XFCN v2.1 by Greg Anderson 14 Sept 1989\r"
/*
| | replace XFCN:
| |
| | Greg Anderson
| | 24 Kerr Hall
| | Social Sciences Computing
| | University of California, Santa Cruz
| | sirkm@ssyx
| |
| | Given a regular expresion and a replacement string, the
| | 'replace' XFCN replaces all strings in the source text
| | that match the regular expression.
| |
| | Example:
| |
| | put replace(reg exp,"replacement",bg fld "Info") into temp
| |
| |
| | KNOWN BUGS:
| |
| | The resulting string cannot be more than 4K larger than the source
| | string.
|*/
#include <MacTypes.h>
#include <FileMgr.h>
#include <SetUpA4.h>
#include "HyperXCmd.h"
#include "XCmdUtil.h"
#include "regexp.h"
/*-----------------------------------------------------------------
| Function types
-----------------------------------------------------------------*/
pascal void main();
void replace();
void replacement();
char searchline();
char copyline();
char advanceline();
/*-----------------------------------------------------------------
| This is the entry point to replace
-----------------------------------------------------------------*/
pascal void main(paramPtr)
XCmdBlockPtr paramPtr;
{
char *list;
int i;
/*
| | Fix up LSC
*/
RememberA0();
SetUpA4();
/*
| | Check for the propper number of parameters
*/
if( (paramPtr->paramCount == 0) )
{
ReturnMsg(paramPtr,ABOUT);
return;
}
if( (paramPtr->paramCount < 3) || (paramPtr->paramCount > 4) )
{
ReturnMsg(paramPtr,"Error in number of parameters.");
return;
}
/*
| | Move all parameters to top of heap and protect them
*/
for (i=0;i<paramPtr->paramCount;i++)
{
MoveHHi(paramPtr->params[i]);
HLock(paramPtr->params[i]);
}
/*
| | Search through flags, if any were specified
*/
regexp_flags = 0; /* From regexp.c */
list = *(paramPtr->params[0]);
if( (paramPtr->paramCount == 4) )
{
while( *list )
{
switch( *list++ )
{
case 'i': regexp_flags |= IGNORE;
break;
case 'm': regexp_flags |= MULTILINE;
break;
case 'f': regexp_flags |= FOLDEDLINE;
break;
case 'b': regexp_flags |= NOBREAKS;
break;
}
}
}
/*
| | Do the xcmd
*/
replace(paramPtr);
/*
| | Unprotect the parameters so they can be freed by HyperCard
*/
for (i=0;i<paramPtr->paramCount;i++)
HUnlock(paramPtr->params[i]);
/*
| | The last thing to do before exiting:
*/
RestoreA4();
}
/*-----------------------------------------------------------------
| Main replace loop
-----------------------------------------------------------------*/
void replace(paramPtr)
XCmdBlockPtr paramPtr;
{
Handle tempBuf;
char *searchstring,
*repstring,
*in,
*out;
int i,
regexpparam,
replaceparam,
textparam,
searchlen;
long handLen;
regexpparam = (paramPtr->paramCount == 4);
replaceparam = regexpparam + 1;
textparam = replaceparam + 1;
/*
| |Create a temporary buffer about 4K larger than the input buffer.
*/
handLen = GetHandleSize(paramPtr->params[textparam]) + 4200L;
tempBuf = NewHandle((long)handLen);
if( !tempBuf )
{
ReturnMsg(paramPtr,"Error allocating memory.");
return;
}
MoveHHi(tempBuf);
HLock(tempBuf);
searchstring = *(paramPtr->params[regexpparam]);
searchlen = greplen(&searchstring);
repstring = *(paramPtr->params[replaceparam]);
in = *(paramPtr->params[textparam]);
out = *tempBuf;
if( searchlen < 0 )
{
DisposHandle(tempBuf);
ReturnMsg(paramPtr,"Error in search string.");
return;
}
while( searchline(searchstring,repstring,&in,&out) );
*out = 0;
paramPtr->returnValue = tempBuf;
}
/*-----------------------------------------------------------------
| Check if the current line contains the search pattern
-----------------------------------------------------------------*/
char searchline(searchstring,rep,in,out)
char *searchstring,
*rep,
**in,
**out;
{
char *initial,
*start,
*end,
**start_p = &start,
**end_p = &end;
/*
| | If there is nothing on the last line, then it is not a line.
*/
if( **in == 0 ) return(0);
if( regexp_flags & BEGINFLAG ) start_p = 0;
if( regexp_flags & ENDFLAG ) end_p = 0;
for(;;)
{
initial = *in;
start = initial;
if( find_regexp(searchstring,*in,start_p,end_p) )
{
/*
| | Copy the beginning portion of the line (before
| | the match) to the output buffer
*/
while( initial < start )
{
*(*out)++ = *(*in)++;
++initial;
}
/*
| | Insert the replacement string into the output buffer
*/
replacement(rep,out);
/*
| | If this match was to the end of the line ('$' flag),
| | then skip to the end of the input buffer line (which
| | must be where the match ended) and copy an end-of-line
| | marker to the output buffer.
*/
if( !end_p )
{
*(*out)++ = '\r';
return( advanceline(in) );
}
/*
| | Skip past the portion of the input that was replaced
*/
*in = end;
/*
| | If this match was from the beginning of the line
| | ('^' flag), then copy everything in the input line
| | after the match into the output buffer.
*/
if( !start_p )
return( copyline(in,out) );
/*
| | If neither '^' nor '$' were specified, but the match
| | still went to the end of the line, add an end-of-line
| | character to the output buffer and exit.
| |
| | If the pointer is not at the end of the line, then
| | the rest of the input line will be checked for
| | other possible matches.
*/
if( end_of_line(end) )
{
*(*out)++ = '\r';
return( *(*in)++ );
}
/*
| | Prevent null regular expressions from looping
| | infinitely--after every null match, skip over
| | one input character (copying it to the output buffer)
*/
if( !(*searchstring) ) *(*out)++ = *(*in)++;
}
else
/*
| | No matches on this line -- just copy the input
| | line to the output buffer.
*/
return( copyline(in,out) );
}
}
/*-----------------------------------------------------------------
| If a pattern is not found, copy the line to the output buffer
-----------------------------------------------------------------*/
char copyline(fieldptr,outputptr)
char **fieldptr,
**outputptr;
{
while( !end_of_line(*fieldptr) )
{
*(*outputptr)++ = *(*fieldptr)++;
}
*(*outputptr)++ = '\r';
return( *(*fieldptr)++ );
}
/*-----------------------------------------------------------------
| The pattern was found & replaced to the end of the line; advance
| the pointer.
-----------------------------------------------------------------*/
char advanceline(fieldptr)
char **fieldptr;
{
while( !end_of_line(*fieldptr) )
(*fieldptr)++;
return( *(*fieldptr)++ );
}
/*-----------------------------------------------------------------
| If a pattern is found, copy the replacement to the output buffer
-----------------------------------------------------------------*/
void replacement(repstring,outputptr)
char *repstring,
**outputptr;
{
char c;
while( (c = *repstring++) )
*(*outputptr)++ = c;
}